﻿using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using System;

namespace SentiWordNet
{
    public class VietSentiWordNet
    {
        #region Private Variables
        private Dictionary<string, ExtractResult> _dict;
        #endregion

        #region Properties
        public string DataFilePath { get; set; }
        #endregion

        #region Contructors
        public VietSentiWordNet(string dataFilePath = "VietSentiWordnet_ver1.0.txt")
        {
            DataFilePath = dataFilePath;
            try
            {
                using (StreamReader sr = new StreamReader(DataFilePath))
                {
                    Process(sr);
                }
            }
            catch (IOException e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private void Process(StreamReader sr)
        {
            _dict = new Dictionary<string, ExtractResult>();
            Dictionary<string, List<double>> _temp = new Dictionary<string, List<double>>();
            string line;

            while (!string.IsNullOrEmpty(line = sr.ReadLine()))
            {
                if (line.Trim()[0] == '#') continue;

                string[] data = line.Split('\t');
                double score = double.Parse(data[2]) - double.Parse(data[3]);
                string[] words = data[4].Split(' ');

                foreach (string w in words)
                {
                    string[] w_n = w.Split('#');
                    w_n[0] += '#' + data[0];

                    int index = int.Parse(w_n[1]) - 1;
                    if (_temp.ContainsKey(w_n[0]))
                    {
                        List<double> v = _temp[w_n[0]];
                        while (index >= v.Count) v.Add(0.0);
                        v[index] = score;
                        _temp[w_n[0]] = v;
                    }
                    else
                    {
                        List<double> v = new List<double>();
                        for (int i = 0; i <= index; ++i) v.Add(0.0);
                        v[index] = score;
                        _temp.Add(w_n[0], v);
                    }
                }
            }

            foreach (var word in _temp.Keys)
            {
                var v = _temp[word];
                double score = 0.0;
                double sum = 0.0;
                for (int i = 0; i < v.Count; ++i)
                    score += (1.0 / (i + 1)) * v[i];
                for (int i = 1; i <= v.Count; ++i)
                    sum += 1.0 / i;
                score /= sum;

                ExtractResult senti = ExtractResult.NotDetermined;
                if (score >= 0.75)
                    senti = ExtractResult.StrongPositive;
                else if (0.25 < score && score <= 0.5)
                    senti = ExtractResult.Positive;
                else if (0 < score && score <= 0.25)
                    senti = ExtractResult.WeakPositive;
                else if (-0.25 <= score && score < 0)
                    senti = ExtractResult.WeakNegative;
                else if (-0.5 <= score && score < -0.25)
                    senti = ExtractResult.Negative;
                else if (score <= -0.75)
                    senti = ExtractResult.StrongNegative;
                _dict.Add(word, senti);
            }
        }

        public ExtractResult Extract(string word, string pos)
        {
            string s = word + '#' + pos;
            if (_dict.ContainsKey(s))
                return _dict[s];
            else
                return ExtractResult.NotDetermined;
        }
        #endregion
    }

    public enum ExtractResult
    {
        StrongNegative = -3,
        Negative       = -2,
        WeakNegative   = -1,
        NotDetermined  = 0,
        WeakPositive   = 1,
        Positive       = 2,
        StrongPositive = 3
    }
}
